package com.rm.zeyou.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rm.zeyou.constant.CommonConstants;
import com.rm.zeyou.constant.NumberConstants;
import com.rm.zeyou.entity.CouponConfig;
import com.rm.zeyou.entity.LimitCouponConfig;
import com.rm.zeyou.entity.LimitCouponMatchesConfig;
import com.rm.zeyou.entity.UserCoupon;
import com.rm.zeyou.exception.ErrorCodeException;
import com.rm.zeyou.exception.ErrorCodeExceptionEnum;
import com.rm.zeyou.mapper.CouponConfigMapper;
import com.rm.zeyou.mapper.LimitCouponConfigMapper;
import com.rm.zeyou.mapper.LimitCouponMatchesConfigMapper;
import com.rm.zeyou.mapper.UserCouponMapper;
import com.rm.zeyou.response.ApiRestResponse;
import com.rm.zeyou.service.UserCouponService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rm.zeyou.util.check.CheckEmptyUtil;
import com.rm.zeyou.vo.request.SelectOrderCanUseCouponListVo;
import com.rm.zeyou.vo.request.SelectUserCouponListVo;
import com.rm.zeyou.vo.request.UserReceiveCouponVo;
import com.rm.zeyou.vo.request.UserReceiveLimitCouponVo;
import com.rm.zeyou.vo.response.SelectUserCouponListResponseVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 用户优惠卷 服务实现类
 * </p>
 *
 * @author YanYang
 * @since 2025-03-12 15:55:09
 */
@Service
public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCoupon> implements UserCouponService {
    @Resource
    private UserCouponMapper userCouponMapper;
    @Resource
    private CouponConfigMapper couponConfigMapper;
    @Resource
    private LimitCouponMatchesConfigMapper limitCouponMatchesConfigMapper;
    @Resource
    private LimitCouponConfigMapper limitCouponConfigMapper;

    @Override
    public ApiRestResponse<PageInfo<SelectUserCouponListResponseVo>> selectUserCouponList(Long userId, SelectUserCouponListVo requestVo) {
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        List<SelectUserCouponListResponseVo> selectUserCouponListResponseVos = userCouponMapper.selectUserCouponListByType(userId, requestVo.getType());
        return ApiRestResponse.success(new PageInfo<>(selectUserCouponListResponseVos));
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public ApiRestResponse<Integer> userReceiveCoupon(Long userId, UserReceiveCouponVo receiveCouponVo) {
        //判断用户是否已经领取
        int userCouponCount = userCouponMapper.selectCount(new LambdaQueryWrapper<UserCoupon>()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getCouponId, receiveCouponVo.getCouponId())).intValue();
        CouponConfig couponConfig = couponConfigMapper.selectById(receiveCouponVo.getCouponId());
        Integer result = 0;
        if (couponConfig.getCouponTotal()<=0){
            throw new ErrorCodeException(ErrorCodeExceptionEnum.COUPON_EMPTY_RECEIVE);
        }
        if (userCouponCount >= couponConfig.getCouponLimitReceiveTotal()) {
            throw new ErrorCodeException(ErrorCodeExceptionEnum.USER_COUPON_IS_RECEIVE);
        } else {
            int min = Math.min(couponConfig.getCouponTotal(), couponConfig.getCouponLimitReceiveTotal());
            //可领取优惠券数量
            int canReceiveCount = min - userCouponCount;
            if (canReceiveCount > 0) {
                for (int i = 0; i < canReceiveCount; i++) {
                    UserCoupon insertUserCoupon = new UserCoupon();
                    insertUserCoupon.setUserId(userId);
                    insertUserCoupon.setCouponFull(couponConfig.getCouponFull());
                    insertUserCoupon.setCouponSubtract(couponConfig.getCouponSubtract());
                    insertUserCoupon.setCouponId(receiveCouponVo.getCouponId());
                    insertUserCoupon.setCloseTime(DateUtil.offsetDay(new Date(), couponConfig.getEffectDay()));
                    userCouponMapper.insert(insertUserCoupon);
                }
                couponConfig.setCouponTotal(couponConfig.getCouponTotal() - canReceiveCount);
                result = couponConfigMapper.updateById(couponConfig);
            }
        }

        if (result <= 0) {
            throw new ErrorCodeException(ErrorCodeExceptionEnum.USER_RECEIVE_ERROR);
        }

        return ApiRestResponse.success(result);
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public ApiRestResponse<Integer> userReceiveLimitCoupon(Long userId, UserReceiveLimitCouponVo receiveCouponVo) {
        LimitCouponConfig limitCouponConfig = limitCouponConfigMapper.selectById(receiveCouponVo.getId());
        if (CheckEmptyUtil.isEmpty(limitCouponConfig)) {
            throw new ErrorCodeException(ErrorCodeExceptionEnum.LIMIT_COUPONCONFIG_EMPTY);
        }
        LimitCouponMatchesConfig limitCouponMatchesConfig = limitCouponMatchesConfigMapper.selectById(limitCouponConfig.getMatchesId());
        if (CheckEmptyUtil.isEmpty(limitCouponMatchesConfig)) {
            throw new ErrorCodeException(ErrorCodeExceptionEnum.LIMIT_COUPONMATCHESCONFIG_EMPTY);
        }
        if (!limitCouponMatchesConfig.getLimitStatus().equals(NumberConstants.ONE_CONSTANTS)) {
            throw new ErrorCodeException(ErrorCodeExceptionEnum.LIMIT_COUPONMATCHESCONFIG_STATUS_ERROR);
        }
        Integer result = 0;
        //计算可领取数量
        int canReceiveCount;

        int limitCouponCount = userCouponMapper.selectCount(new LambdaQueryWrapper<UserCoupon>()
                .eq(UserCoupon::getCouponId, receiveCouponVo.getId())
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getCouponType, NumberConstants.ONE_CONSTANTS)).intValue();
        if (limitCouponCount < limitCouponConfig.getCouponLimitReceiveTotal()) {
            //如果用户已有优惠券数量 < 限时优惠券可领次数 表示还可以在领取
            canReceiveCount = limitCouponConfig.getCouponLimitReceiveTotal() - limitCouponCount;
        } else {
            canReceiveCount = 0;
        }
        if (canReceiveCount <= 0) {
            throw new ErrorCodeException(ErrorCodeExceptionEnum.RECEIVED_LIMIT_COUPONCONFIG);
        }
        for (int i = 0; i < canReceiveCount; i++) {
            UserCoupon insertUserCoupon = new UserCoupon();
            insertUserCoupon.setUserId(userId);
            insertUserCoupon.setCouponFull(limitCouponConfig.getCouponFull());
            insertUserCoupon.setCouponSubtract(limitCouponConfig.getCouponSubtract());
            insertUserCoupon.setCouponId(receiveCouponVo.getId());
            insertUserCoupon.setCloseTime(DateUtil.offsetDay(new Date(), limitCouponConfig.getEffectDay()));
            insertUserCoupon.setCouponType(NumberConstants.ONE_CONSTANTS);
            result = userCouponMapper.insert(insertUserCoupon);
        }
        limitCouponConfig.setCouponTotal(limitCouponConfig.getCouponTotal() - canReceiveCount);
        limitCouponConfigMapper.updateById(limitCouponConfig);
        if (result <= 0) {
            throw new ErrorCodeException(ErrorCodeExceptionEnum.USER_RECEIVE_ERROR);
        }

        return ApiRestResponse.success(result);
    }

    @Override
    public ApiRestResponse<PageInfo<SelectUserCouponListResponseVo>> selectOrderCanUseCouponList(Long userId, SelectOrderCanUseCouponListVo canUseCouponListVo) {
        return ApiRestResponse.success(PageHelper.startPage(canUseCouponListVo.getPageNum(), canUseCouponListVo.getPageSize())
                .doSelectPageInfo(() -> userCouponMapper.selectOrderCanUseCouponList(userId, canUseCouponListVo.getTid())));

    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void updateUserCouponStatus() {
        List<UserCoupon> userCoupons = userCouponMapper.selectList(new LambdaQueryWrapper<UserCoupon>()
                .eq(UserCoupon::getCouponStatus,CommonConstants.USERCOUPON_NOT));
        if (!CheckEmptyUtil.isEmpty(userCoupons)) {
            userCoupons.forEach(userCoupon -> {
                if (new Date().after(userCoupon.getCloseTime())) {
                    // 更新优惠券状态
                    userCoupon.setCouponStatus(CommonConstants.USERCOUPON_EXPIRED);
                    userCouponMapper.updateById(userCoupon);
                }
            });
        }
    }

}
